import React from 'react';
import MiniLayer from '../../layer/MiniLayer';
import Canvas from '../../core/Canvas';
import AxisLayer from '../../layer/AxisLayer';
import Polygon from '../../base/Polygon';
import Point from '../../core/Point';
import OChart from '../../core/OChart';
import MinitePriceLayer from '../../layer/MinitePriceLayer';
import ScaleAction from '../../action/ScaleAction';
import Text from '../../base/Text';
import Rectangle from '../../base/Rectangle';
import { format } from '../../utils/date';
import TimeEventLayer from '../../layer/TimeEventLayer';


let uid = 1;
function uuid() {
  return uid++;
}

export default class extends React.Component {
  constructor(props) {
    super(props);
    this.chartRef = React.createRef();
    this.state = {
      data: props.data || [],
    };
  }

  updateMidRate = ({ midRate }) => {
    this.updateRate(midRate);
  }

  addMiniteOverlying = (overlying) => {
    this.miniLayer.overlyings.push(overlying);
    this.miniLayer.make();
    this.canvas.paint();
  }

  removeMiniteOverlying = (options) => {
    this.miniLayer.overlyings = [];
    this.miniLayer.make();
    this.canvas.paint();
  }

  resize = ( { callback }) => {
    if (
        this.chartRef.current !== undefined
        && this.chartRef.current !== null
    ) {
      this.chartRef.current.innerHTML = '';
      this.init();
      callback && callback();
    }
  }

  setEvents = (option) => {
    if (option.dates) {
      this.timeEventLayer.dates = option.dates;
    }
    if (option.onClick) {
      this.timeEventLayer.onClick = option.onClick;
    }
    this.timeEventLayer.make();
    console.log(this.timeEventLayer, option)
    this.canvas.paint();
  }

  componentDidMount() {
    const { name } = this.props;
    this.init();
    window.addEventListener('resize', (e) => {
      if (
        this.chartRef.current !== undefined
        && this.chartRef.current !== null
      ) {
        this.chartRef.current.innerHTML = '';
        this.init();
      }
    });
    OChart.on(`${name}:updateMinData`, this.updateMidRate);
    OChart.on(`${name}:addMiniteOverlying`, this.addMiniteOverlying);
    OChart.on(`${name}:removeMiniteOverlying`, this.removeMiniteOverlying);
    OChart.on(`${name}:resize`, this.resize);
    OChart.on(`${name}:setEvents`, this.setEvents);
  }

  componentWillReceiveProps(nextProps, nextContext) {
    const { data = [], lastClose = 0, timesNum = 24 * 60 * 60, name = '' } = nextProps;
    if (
      data !== this.props.data
      || lastClose !== this.props.lastClose
      || timesNum !== this.props.timesNum
    ) {
      this.setState({
        data,
      }, () => {
        this.miniLayer.data = this.state.data;
        this.miniLayer.lastClose = lastClose;
        this.miniLayer.timesNum = timesNum;
        this.miniLayer.make();
        this.canvas.paint();
      });

    }

    if (name !== this.props.name) {
      // 移除上一个name的监听
      OChart.remove(`${this.props.name}:updateMinData`, this.updateMidRate);
      OChart.remove(`${this.props.name}:addMiniteOverlying`, this.addMiniteOverlying);
      OChart.remove(`${this.props.name}:removeMiniteOverlying`, this.removeMiniteOverlying);
      OChart.remove(`${this.props.name}:resize`, this.resize);
      OChart.remove(`${this.props.name}:setEvents`, this.setEvents);
      OChart.on(`${name}:updateMinData`, this.updateMidRate);
      OChart.on(`${name}:addMiniteOverlying`, this.addMiniteOverlying);
      OChart.on(`${name}:removeMiniteOverlying`, this.removeMiniteOverlying);
      OChart.on(`${name}:resize`, this.resize);
      OChart.on(`${name}:setEvents`, this.setEvents);
    }
  }

  componentWillUnmount() {
    const { name } = this.props;
    OChart.remove(`${name}:updateMinData`, this.updateMidRate);
    OChart.remove(`${name}:addMiniteOverlying`, this.addMiniteOverlying);
    OChart.remove(`${name}:removeMiniteOverlying`, this.removeMiniteOverlying);
    OChart.remove(`${name}:resize`, this.resize);
    OChart.remove(`${name}:setEvents`, this.setEvents);
  }



  init = () => {
    const { data = [], lastClose = 0, timesNum = 24 * 60 * 60 } = this.props;
    this.canvas = new Canvas({
      ele: this.chartRef.current,
      canAction: false,
    });

    this.axisLayer = new AxisLayer(this.canvas, {
      yAxisMax: 100,
      width: this.canvas.width,
      height: this.canvas.height - 30,
      yAxisMin: 0,
      xAxisLabels: [],
      xAxisPosition: AxisLayer.AxisPosition.BLOCK,
      xAxisGraduations: 5,
      yAxisGraduations: 3,
      yAxisDirect: AxisLayer.AxisDirect.RIGHT,
      yAxisRender: (data) => {
        return {
          text: parseFloat(data).toFixed(2),
          size: 20,
        };
      },
    });
    this.currentTime = new Text(this.canvas, {
      font: 'PingFang SC',
      color: '#FFFFFF',
      size: 20,
      text: '',
    });
    this.currentTimeBox = new Rectangle(this.canvas, {
      width: 10,
      height: 22,
      color: '#6384FD',
    });

    this.currentPrice = new Text(this.canvas, {
      font: 'PingFang SC',
      color: '#FFFFFF',
      size: 20,
      text: ''
    });
    this.currentPriceBox = new Rectangle(this.canvas, {
      width: 10,
      height: 22,
      color: '#6384FD'
    });

    this.timeEventLayer = new TimeEventLayer(this.canvas, {
      width: this.canvas.width,
      height: this.canvas.height - 30,
      dateStart: data.length > 0 ? data[0].datetime : 0,
      dates: [],
      timeStep: 1,
    });
    this.timeEventLayer.setPosition(0, 30);
    this.axisLayer.setPosition(0, 30);
    const marginHeight = Math.round(this.canvas.height * 0.1);
    this.miniLayer = new MiniLayer(this.canvas, {
      width: this.canvas.width,
      height: this.canvas.height - marginHeight - 30,
      timesNum,
      data,
      lastClose,
      color: '#F6A835',
    });
    this.miniLayer.setPosition(0, marginHeight / 2 + 30);
    this.priceLayer = new MinitePriceLayer(this.canvas, {
      width: this.canvas.width,
      height: this.canvas.height - 30,
      color: '#F6A835',
      size: 5,
    });
    this.priceLayer.setPosition(0, 30);
    this.polygon = new Polygon(this.canvas, {
      color: '#F6A835',
    });
    this.timeStart = new Text(this.canvas, {
      text: '',
      font: 'PingFang SC',
      size: 16,
      color: '#FFFFFF'
    });
    this.timeStart.setPosition(0, 10);
    this.timeEnd = new Text(this.canvas, {
      text: '',
      font: 'PingFang SC',
      size: 16,
      color: '#FFFFFF',
    });
    this.timeEnd.setPosition(this.canvas.width - 5 * 16 * 0.518, 10);
    this.polygon.alpha = 0.2;
    this.miniLayer.setOnMaked((option) => {
      const { points, yStep, pcg, lastClose, xStep } = option;
      let yAxisMax = lastClose + (marginHeight / 2) / yStep + pcg;
      let yAxisMin = lastClose - (marginHeight / 2) / yStep - pcg;
      this.axisLayer.yAxisMax =  yAxisMax;
      this.axisLayer.yAxisMin = yAxisMin;
      this.axisLayer.make();
      this.polygon.points = [new Point(0, 30)]
        .concat(points, [new Point(points[points.length - 1].x, 30)]);
      this.priceLayer.setPoint(new Point(points[points.length - 1].x, points[points.length - 1].y - 30));
      this.currentTime.text = format(new Date(this.miniLayer.data[this.miniLayer.data.length - 1].datetime), 'hh:mm');
      this.currentTimeBox.setPosition(points[points.length - 1].x - this.currentTime.text.length * 0.518 * 10 - 4, 3);
      this.currentTimeBox.width = this.currentTime.text.length * 0.518 * 20 + 8;
      this.currentTime.setPosition(points[points.length - 1].x - this.currentTime.text.length * 0.518 * 10, 5);
      this.currentPrice.text = `${this.miniLayer.data[this.miniLayer.data.length - 1].price}`;
      this.currentPriceBox.width = this.currentPrice.text.length * 0.518 * 20 + 8;
      this.currentPrice.setPosition(4, points[points.length - 1].y - 10);
      this.currentPriceBox.setPosition(0, points[points.length - 1].y - 11);
      this.timeStart.text = format(new Date(this.miniLayer.data[0].datetime), 'hh:mm');
      this.timeEnd.text = format(new Date(this.miniLayer.data[0].datetime + 23 * 60 * 60 * 1000), 'hh:mm');
      if (this.miniLayer.data.length > 1) {
        this.timeEventLayer.dateStart = this.miniLayer.data[0].datetime;
        this.timeEventLayer.timeStep = xStep / (this.miniLayer.data[1].datetime - this.miniLayer.data[0].datetime);
        this.timeEventLayer.make();
      }

    });
    this.scaleAction = new ScaleAction(1);
    this.miniLayer.make();
    this.canvas.addChild(
        this.miniLayer,
        this.polygon,
        this.axisLayer,
        this.priceLayer,
        this.currentTimeBox,
        this.currentTime,
        this.currentPriceBox,
        this.currentPrice,
        this.timeStart,
        this.timeEnd,
        this.timeEventLayer,

    );

    this.canvas.paint();
  }

  updateRate(midRate) {
    let { data } = this.state;
    const currentTime = new Date().getTime();
    if (data.length > 0) {
      const last = data[data.length - 1];
      if (currentTime - last.datetime >= 60000) {
        data.push({
          price: midRate,
          datetime: currentTime,
        });
      } else {
        data[data.length - 1].price = midRate;
      }
    } else {
      data.push({
        price: midRate,
        datetime: currentTime,
      });
    }
    this.setState({
      data,
    }, () => {
      this.miniLayer.data = this.state.data;
      this.timeStart.text = format(new Date(this.state.data[0].datetime), 'hh:mm');
      this.timeEnd.text = format(new Date(this.state.data[0].datetime + 23 * 60 * 60 * 1000), 'hh:mm');
      this.miniLayer.make();
      this.scaleAction.reset(this.priceLayer.bigCircle);
      this.canvas.paint();
    });
  }

  render() {
    const { className = '' } = this.props;
    return (
      <div ref={this.chartRef} className={className} />
    );
  }
}
